﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DriveBeamEditor.Controls.BeamNG.Forms;
using JBeamLibrary.Tools;
using JBeamLibrary.VehicleParts;
using JBeamLibrary.VehicleParts.Elements;

namespace DriveBeamEditor.Controls.BeamNG.VehiclePartConfig
{
    public partial class VehiclePartSlots : VehiclePartControl
    {
        #region Fields

        #endregion

        #region Properties

        public Slot SelectedSlot
        {
            get { return slotsBindingSource.Current as Slot; }
            set
            {
                slotsBindingSource.Position = slotsBindingSource.IndexOf(value);
                UpdateUI();
            }
        }

        #endregion

        #region CTORs

        public VehiclePartSlots()
        {
            InitializeComponent();
        }

        #endregion

        #region Events

        #region Binding source

        private void slotsBindingSource_AddingNew(object sender, AddingNewEventArgs e)
        {
            if (DesignMode || VehiclePart == null)
            {
                e.NewObject = new Slot("", "", null);
                return;
            }

            /* Avoid loop */
            if (e.NewObject is Slot) return;

            /* Ask for a name */
            var name = Randomizer.GetRandomName();
            var nameOk = false;
            while (!nameOk)
            {
                /* Enter name */
                using (var input = TextInputForm.GetNew(@"Enter a unique slot type name", @"Slot type", true,
                    string.Format("{0}_", VehiclePart.File.Parent.Name), @"Please provide a slot type"))
                {
                    if (input.ShowDialog(this) == DialogResult.OK)
                        name = input.InputText;
                    else
                        break;
                }

                /* Check for existence */
                if (VehiclePart.Slots.OfType<Slot>()
                    .Any(slot => slot.TypeName.ToUpperInvariant().Equals(name.ToUpperInvariant())))
                {
                    MessageBox.Show(this, @"The provided slot type already exists. Please choose another one",
                        @"Duplicate found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }

                /* Only ok if we pressed 'Ok' (see above) */
                else nameOk = true;
            }

            /* Cancel new row if name was not chosen */
            if (!nameOk)
            {
                slotsBindingSource.EndEdit();
                grid.NotifyCurrentCellDirty(true);
                grid.EndEdit();
                grid.NotifyCurrentCellDirty(false);
                return;
            }

            /* Create new slot */
            e.NewObject = new Slot(name, name, VehiclePart);
        }

        private void slotsBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            UpdateUI();
        }

        #endregion

        #region Data grid view

        private void grid_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            /* Clicks on headers */
            if (e.ColumnIndex < 0 || e.RowIndex < 0) return;

            /* Get column & row & cell */
            var col = grid.Columns[e.ColumnIndex];

            /* Select a part */
            if (col.Name.Equals("columnDefaultPart"))
            {
                pddPartSelection.Show(grid, grid.PointToClient(Cursor.Position));
            }
        }

        private void grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            /* Clicks on headers */
            if (e.ColumnIndex < 0 || e.RowIndex < 0) return;

            /* Get column & row & cell */
            var col = grid.Columns[e.ColumnIndex];
            var row = grid.Rows[e.RowIndex];

            /* Validate new row */
            if (row.IsNewRow && col.Name.Equals("columnDelete"))
            {
                slotsBindingSource.EndEdit();
                grid.NotifyCurrentCellDirty(true);
                grid.EndEdit();
                grid.NotifyCurrentCellDirty(false);
            }

            /* Select a part for the current cell */
            else if (col.Name.Equals("columnDefaultPart"))
            {
                pddPartSelection.Show(grid, grid.PointToClient(Cursor.Position));
            }

            /* Delete the current row */
            else if (col.Name.Equals("columnDelete"))
            {
                grid.Rows.RemoveAt(e.RowIndex);
            }
        }

        private void grid_UserAddedRow(object sender, DataGridViewRowEventArgs e)
        {

        }

        private void grid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
        }

        private void grid_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            /* Not any better yet... */
            return;

            /* Get info */
            var column = grid.Columns[e.ColumnIndex];
            var value = grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToStringOrEmpty();

            /* Missing slot info */
            if ((column == columnDescription || column == columnType) && string.IsNullOrEmpty(value))
            {
                MessageBox.Show(
                    this,
                    @"Please fill in all required slot fields",
                    @"Required fields",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation
                );
                e.Cancel = true;
                return;
            }

            /* Slot exists */
            if (column == columnType && grid.Rows.OfType<DataGridViewRow>().Count(row => row.Cells[e.ColumnIndex].Value.SafeEquals(value)) > 1)
            {
                MessageBox.Show(
                    this,
                    @"The specified slot type already exists",
                    @"Duplicate value",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation
                );
                e.Cancel = true;
                return;
            }
        }

        #endregion

        #region Popups

        private void pcPartSelection_VehiclePartSelected(object sender, VehiclePart e)
        {
            if (grid.CurrentRow == null || grid.CurrentCell == null || e == null) return;

            var slot = grid.CurrentRow.DataBoundItem as Slot;
            if (slot == null) return;

            var col = grid.Columns[grid.CurrentCell.ColumnIndex];
            if (col == null) return;

            if (col.DataPropertyName.Equals("DefaultPartName"))
            {
                slot.DefaultPartName = e.Name;
                UpdateUI();
            }
        }

        #endregion

        #region Buttons

        #endregion

        private void btSelectSlot_SlotSelected(object sender, Slot e)
        {
            tbParentSlot.Text = e.TypeName;
        }

        #endregion

        #region Methods

        public override void UpdateUI(Control parent = null)
        {
            base.UpdateUI(parent);

            if (parent != null) return;
        }

        protected override void OnVehiclePartChanged()
        {
            if (VehiclePart != null)
            {
                btSelectSlot.Vehicle = VehiclePart.File.Parent;
            }
            pcPartSelection.Vehicle = VehiclePart != null ? VehiclePart.File.Parent : null;
            base.OnVehiclePartChanged();
        }

        #endregion
    }
}
